#!/usr/bin/env node

/**
 * 日志清理脚本
 * 
 * 此脚本用于清理旧的日志文件，保持日志目录整洁
 * 可以通过cron定时任务来定期执行此脚本
 * 
 * 使用方法: node clean-logs.js [days] [maxSize]
 * - days: 要保留的日志文件天数，默认为7天
 * - maxSize: 日志文件夹的最大大小（MB），默认为100MB
 * 
 * 示例cron配置（每天凌晨3点执行）:
 * 0 3 * * * cd /path/to/nodejs-project && node scripts/clean-logs.js >> logs/clean.log 2>&1
 */

const fs = require('fs');
const path = require('path');
const { exec } = require('child_process');

// 获取命令行参数
const args = process.argv.slice(2);
const daysToKeep = parseInt(args[0]) || 7; // 默认保留7天的日志
const maxSizeMB = parseInt(args[1]) || 100; // 默认日志文件夹最大100MB

// 日志目录路径
const logDir = path.join(__dirname, '..', 'logs');

// 输出日志
const log = (message) => {
    const timestamp = new Date().toISOString();
    console.log(`[${timestamp}] ${message}`);
};

// 删除旧的日志文件
const cleanOldLogs = () => {
    // 检查日志目录是否存在
    if (!fs.existsSync(logDir)) {
        log(`日志目录不存在: ${logDir}`);
        return;
    }
    
    try {
        log('开始清理旧日志文件...');
        
        // 获取当前时间
        const now = new Date();
        
        // 计算过期时间（当前时间减去保留天数）
        const expiryTime = new Date(now.getTime() - (daysToKeep * 24 * 60 * 60 * 1000));
        
        // 读取日志目录中的所有文件
        const files = fs.readdirSync(logDir);
        
        // 记录删除的文件数量和大小
        let deletedCount = 0;
        let deletedSizeBytes = 0;
        
        // 遍历文件
        for (const file of files) {
            // 跳过当前日志文件（没有日期后缀的文件）
            if (file === 'access.log' || file === 'error.log' || file === 'db.log' || file === 'clean.log') {
                continue;
            }
            
            const filePath = path.join(logDir, file);
            
            // 获取文件状态
            const stats = fs.statSync(filePath);
            
            // 检查文件是否为旧日志文件（有日期后缀）
            if (file.includes('.log.') && stats.isFile()) {
                const fileTime = stats.mtime; // 文件修改时间
                
                // 如果文件修改时间早于过期时间，则删除文件
                if (fileTime < expiryTime) {
                    const fileSizeBytes = stats.size;
                    
                    // 删除文件
                    fs.unlinkSync(filePath);
                    
                    // 更新统计信息
                    deletedCount++;
                    deletedSizeBytes += fileSizeBytes;
                    
                    log(`已删除旧日志文件: ${file} (${(fileSizeBytes / 1024 / 1024).toFixed(2)} MB)`);
                }
            }
        }
        
        // 输出统计信息
        const deletedSizeMB = (deletedSizeBytes / 1024 / 1024).toFixed(2);
        log(`清理完成，已删除 ${deletedCount} 个旧日志文件，释放了 ${deletedSizeMB} MB 空间`);
        
        return { deletedCount, deletedSizeBytes };
    } catch (error) {
        log(`清理旧日志文件时出错: ${error.message}`);
        return { deletedCount: 0, deletedSizeBytes: 0 };
    }
};

// 检查日志目录大小并清理
const checkLogDirSize = () => {
    try {
        log('检查日志目录大小...');
        
        // 计算目录大小（跨平台兼容）
        const calculateDirSize = () => {
            let totalSize = 0;
            const files = fs.readdirSync(logDir);
            
            for (const file of files) {
                const filePath = path.join(logDir, file);
                try {
                    const stats = fs.statSync(filePath);
                    if (stats.isFile()) {
                        totalSize += stats.size;
                    }
                } catch (error) {
                    log(`无法获取文件信息 ${filePath}: ${error.message}`);
                }
            }
            
            return totalSize;
        };
        
        // 获取目录总大小（字节）
        const dirSizeBytes = calculateDirSize();
        const dirSizeMB = dirSizeBytes / (1024 * 1024);
        
        log(`当前日志目录大小: ${dirSizeMB.toFixed(2)} MB`);
        
        // 如果目录大小超过最大限制，强制清理旧日志
        if (dirSizeMB > maxSizeMB) {
            log(`日志目录大小 (${dirSizeMB.toFixed(2)} MB) 超过限制 (${maxSizeMB} MB)，强制清理...`);
            
            // 获取所有日志文件并按修改时间排序
            const files = fs.readdirSync(logDir)
                .filter(file => file.includes('.log.') && fs.statSync(path.join(logDir, file)).isFile())
                .map(file => {
                    const filePath = path.join(logDir, file);
                    const stats = fs.statSync(filePath);
                    return {
                        name: file,
                        path: filePath,
                        mtime: stats.mtime.getTime(),
                        size: stats.size
                    };
                })
                .sort((a, b) => a.mtime - b.mtime); // 按时间从旧到新排序
            
            // 计算要保留的文件数量
            const keepCount = Math.min(daysToKeep, files.length);
            const filesToDelete = files.slice(0, files.length - keepCount);
            
            // 删除旧文件
            let deletedSize = 0;
            for (const file of filesToDelete) {
                try {
                    fs.unlinkSync(file.path);
                    deletedSize += file.size;
                    log(`强制清理: 已删除 ${file.name} (${(file.size / 1024 / 1024).toFixed(2)} MB)`);
                } catch (error) {
                    log(`删除文件 ${file.path} 失败: ${error.message}`);
                }
            }
            
            log(`强制清理完成，删除了 ${filesToDelete.length} 个文件，释放了 ${(deletedSize / 1024 / 1024).toFixed(2)} MB 空间`);
            
            // 再次计算目录大小
            const newDirSizeBytes = calculateDirSize();
            const newDirSizeMB = newDirSizeBytes / (1024 * 1024);
            log(`强制清理后的日志目录大小: ${newDirSizeMB.toFixed(2)} MB`);
        } else {
            log(`日志目录大小在限制范围内，无需强制清理`);
        }
    } catch (error) {
        log(`检查日志目录大小时出错: ${error.message}`);
    }
};

// 运行清理任务
cleanOldLogs();
checkLogDirSize();

// 输出使用说明
log(`日志清理脚本完成，配置: 保留 ${daysToKeep} 天的日志，日志目录最大 ${maxSizeMB} MB`); 